from rest_framework.views import APIView
from rest_framework.response import Response
from .serializers import CartSerializer, CartSkuSerializer, CartSkuDeleteSerializer, CartSelectAllSerializer
from utils.dictconvert import dumps, loads
from . import constants
from goods.models import SKU
from rest_framework import serializers
from rest_framework import status
from django_redis import get_redis_connection


class CartView(APIView):
    """重写perform_authentication认证方法 即不进行认证"""

    def perform_authentication(self, request):
        pass

    def post(self, request):
        """
        添加:
        接收 返回参数:sku_id 商品sku id
                    count 数量
                    selected 是否勾选

        redis存取格式:
            {
                sku_id:"{
                "count":count,
                "selected":selected}

            }"""
        # 反序列化获取validated_data
        serializer = CartSerializer(data=request.data)
        # 验证失败后抛异常
        serializer.is_valid(raise_exception=True)
        sku_id = serializer.validated_data['sku_id']
        count = serializer.validated_data['count']
        # 用户是否登录
        try:
            user = request.user
        except:
            user = None
        response = Response(serializer.validated_data)
        if user is None:
            """未登录 将数据存入cookies"""
            # 先拿到cookies的数据 再增加 否则会覆盖
            cart = request.COOKIES.get('cart')
            if cart:
                cart_dict = loads(cart)
            else:
                cart_dict = {}
            # 判断购物车里是否有该商品
            if sku_id in cart_dict:
                cart_dict[sku_id]["count"] += count
            else:
                cart_dict[sku_id] = {
                    "count": count,
                    "selected": True
                }
            cart_str = dumps(cart_dict)
            response.set_cookie('cart', cart_str, max_age=constants.CART_COOKIE_EXPIRES)
        else:
            """登录后 将数据存入redis"""
            key = "cart%d" % user.id
            redis_cli = get_redis_connection('cart')
            redis_cli.hincrby(key, sku_id, count)

        return response

    def get(self, request):
        """查询
        返回参数: id count selected name default_image_url price"""
        try:
            user = request.user
        except:
            user = None
        if user is None:
            cart = request.COOKIES.get('cart')
            if cart:
                cart_dict = loads(cart)
            else:
                cart_dict = {}
        else:
            redis_cli = get_redis_connection('cart')
            cart_redis = redis_cli.hgetall("cart%d" % user.id)
            cart_dict = {}
            for sku_id, count in cart_redis.items():
                cart_dict[int(sku_id)] = {
                    "count": int(count)
                }
            cart_selected = redis_cli.smembers("cart_selected%d" % user.id)
            # 将字节型的sku_id列表转换成int型
            cart_selected = [int(sku_id) for sku_id in cart_selected]
            # set中的 sku_id 在hash中取到
            for sku_id in cart_dict:
                if sku_id in cart_selected:
                    cart_dict[int(sku_id)]["selected"] = True
                else:
                    cart_dict[int(sku_id)]["selected"] = False
        skus = SKU.objects.filter(id__in=cart_dict.keys())
        # 添加输出字段count selected
        for sku in skus:
            sku.count = cart_dict[sku.id]["count"]
            sku.selected = cart_dict[sku.id]["selected"]
        # 序列化输出
        serializer = CartSkuSerializer(skus, many=True)
        return Response(serializer.data)

    def put(self, request):
        """修改"""
        serializer = CartSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        sku_id = serializer.validated_data['sku_id']
        count = serializer.validated_data['count']
        selected = serializer.validated_data['selected']
        response = Response(serializer.validated_data)
        try:
            user = request.user
        except:
            user = None
        if user is None:
            cart = request.COOKIES.get('cart')
            if not cart:
                raise serializers.ValidationError("购物车为空")
            cart_dict = loads(cart)
            if sku_id in cart_dict:
                cart_dict[sku_id] = {
                    "count": count,
                    "selected": selected
                }
            cart_str = dumps(cart_dict)
            response.set_cookie("cart", cart_str, max_age=constants.CART_COOKIE_EXPIRES)
        else:
            redis_cli = get_redis_connection('cart')
            redis_cli.hset('cart%d' % user.id, sku_id, count)
            if selected:
                redis_cli.sadd('cart_selected%d' % user.id, sku_id)
            else:
                redis_cli.srem('cart_selected%d' % user.id, sku_id)
        return response

    def delete(self, request):
        """删除"""
        serializers = CartSkuDeleteSerializer(data=request.data)
        serializers.is_valid(raise_exception=True)
        sku_id = serializers.validated_data['sku_id']
        response = Response(status=status.HTTP_204_NO_CONTENT)
        try:
            user = request.user
        except:
            user = None
        if user is None:
            cart = request.COOKIES.get('cart')
            if not cart:
                raise serializers.ValidationError("购物车为空")
            cart_dict = loads(cart)
            if sku_id in cart_dict:
                del cart_dict[sku_id]
            cart_str = dumps(cart_dict)
            response.set_cookie('cart', cart_str, max_age=constants.CART_COOKIE_EXPIRES)

        else:
            redis_cli = get_redis_connection('cart')
            redis_cli.hdel("cart%d" % user.id, sku_id)
            redis_cli.srem("cart_selected%d" % user.id,sku_id)
        return response


class CartSelectAllView(APIView):
    def perform_authentication(self, request):
        pass

    def put(self, request):
        serializer = CartSelectAllSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        selected = serializer.validated_data['selected']
        response = Response({'message': 'ok'})
        try:
            user = request.user
        except:
            user = None
        if user is None:
            cart = request.COOKIES.get('cart')
            if not cart:
                raise serializers.ValidationError("购物车为空")
            cart_dict = loads(cart)
            for sku_id in cart_dict:
                cart_dict[sku_id]["selected"] = selected
            cart_str = dumps(cart_dict)
            response.set_cookie('cart', cart_str, max_age=constants.CART_COOKIE_EXPIRES)

        else:
            redis_cli = get_redis_connection('cart')
            sku_ids = redis_cli.hkeys("cart%d" % user.id)
            if selected:
                redis_cli.sadd("cart_selected%d" % user.id, *sku_ids)
            else:
                redis_cli.srem("cart_selected%d" % user.id, *sku_ids)
        return response
